package cn.tanghom.support.id;

import java.io.Serializable;
import java.util.Date;
import java.util.UUID;

import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.Version;


/**
 * 统一定义id的entity基类.
 * <p/>
 * 基类统一定义id的属性名称、数据类型、列名映射及生成策略.
 * 子类可重载getId()函数重定义id的列名映射和生成策略.
 *
 * @author calvin
 */
//JPA 基类的标识
@MappedSuperclass
public abstract class UUIDEntity  implements Serializable{	
	private static final long serialVersionUID = 2799754735942056073L;

	public static String generate() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }
	  
	protected String id;

    @Id   
    @GeneratedValue(generator = "system-uuid")
    //@GenericGenerator(name = "system-uuid", strategy = "uuid")
    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }
    

    /**
     * 创建时间, 默认为当前时间值
     */
    protected long created = System.currentTimeMillis();    

    /*
    * 实现数据 乐观锁
    * */
    // Optimistic lock
    @Version
    protected long changed = 0;
    

    public UUIDEntity() {
    }


    public Date createTime() {
        return new Date(created);
    }
    
    public Date updateTime() {
        return new Date(changed);
    }

    /**
     * 设置Domain的创建时间并返回实体本身.
     * Builder设计模式的变种
     *
     * @param createTime createTime 可以为空，则为当前时间
     * @param <T>        AbstractDomain subclass
     * @return Current domain
     */
    @SuppressWarnings("unchecked")
    public <T extends UUIDEntity> T createTime(Date createTime) {
    	if(createTime!=null)
    		this.created = createTime.getTime();       
        return (T) this;
    }
    
    @SuppressWarnings("unchecked")
    public <T extends UUIDEntity> T updateTime(Date updateTime) {
    	if(updateTime!=null){
    		version(updateTime.getTime());
    	}
    	else{
    		version(System.currentTimeMillis());
    	}
        return (T) this;
    }

    public long version() {
        return changed;
    }

    @SuppressWarnings("unchecked")
    public <T extends UUIDEntity> T version(long version) {
    	if(version<=this.changed){
    		throw new IllegalArgumentException("new version value must great than current value.");
    	}
        this.changed = version;
        return (T) this;
    }
    
    //may not java bean property
    public String uuid() {
    	if(id == null){
    		id = generate();
    	}
        return id;
    }

    @SuppressWarnings("unchecked")
    public <T extends UUIDEntity> T uuid(String guid) {
        this.id = guid;
        return (T) this;
    }

    //java bean property：

    protected long getCreated() {
		return created;
	}


    protected void setCreated(long created) {
		this.created = created;
	}


    protected long getChanged() {
		return changed;
	}


    protected void setChanged(long changed) {
		this.changed = changed;
	}
    
}
